import {
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
  Inject,
  forwardRef,
  Logger,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In, Not } from 'typeorm';
import { Friendship, FriendshipStatus } from './entities/friendship.entity';
import { User } from '../auth/entities/user.entity';
import { SendFriendRequestDto } from './dto/friend-request.dto';
import { MessagesService } from '../messages/messages.service';
import { NotificationsGateway } from '../notifications/notifications.gateway';
import { NotificationType } from '../messages/entities/notification.entity';

@Injectable()
export class FriendsService {
  private readonly logger = new Logger(FriendsService.name);

  constructor(
    @InjectRepository(Friendship)
    private readonly friendshipRepository: Repository<Friendship>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    @Inject(forwardRef(() => MessagesService))
    private readonly messagesService: MessagesService,
    private readonly notificationsGateway: NotificationsGateway,
  ) { }

  /**
   * 发送好友请求
   */
  async sendFriendRequest(
    dto: SendFriendRequestDto,
    userId: number,
  ): Promise<Friendship> {
    const { friendId, remark } = dto;

    // 不能添加自己为好友
    if (friendId === userId) {
      throw new BadRequestException('不能添加自己为好友');
    }

    // 检查目标用户是否存在
    const friend = await this.userRepository.findOne({
      where: { id: friendId },
    });
    if (!friend) {
      throw new NotFoundException('用户不存在');
    }

    // 检查是否已存在关系（任意方向）
    const existingFriendship = await this.friendshipRepository.findOne({
      where: [
        { userId, friendId },
        { userId: friendId, friendId: userId },
      ],
    });

    if (existingFriendship) {
      if (existingFriendship.status === FriendshipStatus.BLOCKED) {
        throw new ConflictException('无法添加该用户');
      }
      if (existingFriendship.status === FriendshipStatus.PENDING) {
        throw new ConflictException('已发送过好友请求，请等待对方回应');
      }
      if (existingFriendship.status === FriendshipStatus.ACCEPTED) {
        throw new ConflictException('已经是好友了');
      }
      // 如果之前被拒绝，更新现有记录为待处理状态
      if (existingFriendship.status === FriendshipStatus.REJECTED) {
        // 如果是当前用户发起的请求被拒绝，更新现有记录
        if (existingFriendship.userId === userId && existingFriendship.friendId === friendId) {
          existingFriendship.status = FriendshipStatus.PENDING;
          existingFriendship.remark = remark || null;
          existingFriendship.createdAt = new Date(); // 重置创建时间
          const savedFriendship = await this.friendshipRepository.save(existingFriendship);

          // 获取申请人信息
          const user = await this.userRepository.findOne({
            where: { id: userId },
          });

          // 创建系统通知
          try {
            await this.messagesService.createNotification({
              userId: friendId, // 接收者
              triggerId: userId, // 触发者
              type: NotificationType.FRIEND_REQUEST,
              title: '新的好友申请',
              content: `${user?.nickname || user?.username || '用户'} 请求添加你为好友${remark ? `：${remark}` : ''}`,
              data: {
                friendshipId: savedFriendship.id,
                requesterId: userId,
                requesterName: user?.nickname || user?.username,
                requesterAvatar: user?.avatar,
                remark,
              },
            });
            this.logger.log(`已为用户 ${friendId} 创建好友申请通知`);
          } catch (error) {
            this.logger.error(`创建好友申请通知失败：${error.message}`);
          }

          // 如果用户在线，通过 WebSocket 实时推送
          if (this.notificationsGateway.isUserOnline(friendId)) {
            this.notificationsGateway.sendToUser(friendId, 'friend-request', {
              type: 'FRIEND_REQUEST',
              friendshipId: savedFriendship.id,
              requester: {
                id: userId,
                username: user?.username,
                nickname: user?.nickname,
                avatar: user?.avatar,
              },
              remark,
            });
            this.logger.log(
              `已通过 WebSocket 向用户 ${friendId} 推送好友申请消息`,
            );
          } else {
            this.logger.log(`用户 ${friendId} 不在线，跳过 WebSocket 推送`);
          }

          return savedFriendship;
        }
        // 如果是对方之前发起的请求被当前用户拒绝，现在当前用户想添加对方
        // 由于方向不同，不会违反唯一索引，但为了数据一致性，我们删除旧记录并创建新记录
        else if (existingFriendship.userId === friendId && existingFriendship.friendId === userId) {
          // 删除旧记录
          await this.friendshipRepository.remove(existingFriendship);
          // 继续执行下面的创建逻辑
        }
      }
    }

    // 获取申请人信息
    const user = await this.userRepository.findOne({
      where: { id: userId },
    });

    // 创建好友请求
    const friendship = this.friendshipRepository.create({
      userId,
      friendId,
      status: FriendshipStatus.PENDING,
      remark,
    });

    const savedFriendship = await this.friendshipRepository.save(friendship);

    // 创建系统通知
    try {
      await this.messagesService.createNotification({
        userId: friendId, // 接收者
        triggerId: userId, // 触发者
        type: NotificationType.FRIEND_REQUEST,
        title: '新的好友申请',
        content: `${user?.nickname || user?.username || '用户'} 请求添加你为好友${remark ? `：${remark}` : ''}`,
        data: {
          friendshipId: savedFriendship.id,
          requesterId: userId,
          requesterName: user?.nickname || user?.username,
          requesterAvatar: user?.avatar,
          remark,
        },
      });
      this.logger.log(`已为用户 ${friendId} 创建好友申请通知`);
    } catch (error) {
      this.logger.error(`创建好友申请通知失败：${error.message}`);
    }

    // 如果用户在线，通过 WebSocket 实时推送
    if (this.notificationsGateway.isUserOnline(friendId)) {
      this.notificationsGateway.sendToUser(friendId, 'friend-request', {
        type: 'FRIEND_REQUEST',
        friendshipId: savedFriendship.id,
        requester: {
          id: userId,
          username: user?.username,
          nickname: user?.nickname,
          avatar: user?.avatar,
        },
        remark,
        createdAt: savedFriendship.createdAt,
      });
      this.logger.log(`已通过 WebSocket 向用户 ${friendId} 推送好友申请`);
    } else {
      this.logger.log(`用户 ${friendId} 不在线，跳过 WebSocket 推送`);
    }

    return savedFriendship;
  }

  /**
   * 接受好友请求
   */
  async acceptFriendRequest(requestId: number, userId: number): Promise<void> {
    const request = await this.friendshipRepository.findOne({
      where: { id: requestId, friendId: userId },
    });

    if (!request) {
      throw new NotFoundException('好友请求不存在');
    }

    if (request.status !== FriendshipStatus.PENDING) {
      throw new BadRequestException('该请求已处理');
    }

    // 更新状态为已接受
    request.status = FriendshipStatus.ACCEPTED;
    await this.friendshipRepository.save(request);

    // 更新双方的好友计数
    await this.userRepository.increment({ id: userId }, 'followingCount', 1);
    await this.userRepository.increment(
      { id: request.userId },
      'followingCount',
      1,
    );
    await this.userRepository.increment({ id: userId }, 'followersCount', 1);
    await this.userRepository.increment(
      { id: request.userId },
      'followersCount',
      1,
    );

    // 获取接受者信息
    const accepter = await this.userRepository.findOne({
      where: { id: userId },
    });

    // 创建系统通知（通知申请人）
    try {
      await this.messagesService.createNotification({
        userId: request.userId, // 接收者（申请人）
        triggerId: userId, // 触发者（接受者）
        type: NotificationType.FRIEND_ACCEPTED,
        title: '好友申请已通过',
        content: `${accepter?.nickname || accepter?.username || '用户'} 接受了你的好友申请`,
        data: {
          friendshipId: request.id,
          accepterId: userId,
          accepterName: accepter?.nickname || accepter?.username,
          accepterAvatar: accepter?.avatar,
        },
      });
      this.logger.log(`已为用户 ${request.userId} 创建好友申请通过通知`);
    } catch (error) {
      this.logger.error(`创建好友申请通过通知失败：${error.message}`);
    }

    // 如果申请人在线，通过 WebSocket 实时推送
    if (this.notificationsGateway.isUserOnline(request.userId)) {
      this.notificationsGateway.sendToUser(request.userId, 'friend-accepted', {
        type: 'FRIEND_ACCEPTED',
        friendshipId: request.id,
        accepter: {
          id: userId,
          username: accepter?.username,
          nickname: accepter?.nickname,
          avatar: accepter?.avatar,
        },
        acceptedAt: new Date(),
      });
      this.logger.log(
        `已通过 WebSocket 向用户 ${request.userId} 推送好友申请通过消息`,
      );
    } else {
      this.logger.log(`用户 ${request.userId} 不在线，跳过 WebSocket 推送`);
    }
  }

  /**
   * 拒绝好友请求
   */
  async rejectFriendRequest(requestId: number, userId: number): Promise<void> {
    const request = await this.friendshipRepository.findOne({
      where: { id: requestId, friendId: userId },
    });

    if (!request) {
      throw new NotFoundException('好友请求不存在');
    }

    // 如果已经是拒绝状态，直接返回（防止重复操作）
    if (request.status === FriendshipStatus.REJECTED) {
      return;
    }

    if (request.status !== FriendshipStatus.PENDING) {
      throw new BadRequestException('该请求已处理');
    }

    // 更新状态为已拒绝
    request.status = FriendshipStatus.REJECTED;
    await this.friendshipRepository.save(request);
  }

  /**
   * 删除好友
   */
  async removeFriend(friendId: number, userId: number): Promise<void> {
    // 查找好友关系（双向）
    const friendship = await this.friendshipRepository.findOne({
      where: [
        { userId, friendId, status: FriendshipStatus.ACCEPTED },
        {
          userId: friendId,
          friendId: userId,
          status: FriendshipStatus.ACCEPTED,
        },
      ],
    });

    if (!friendship) {
      throw new NotFoundException('好友关系不存在');
    }

    // 删除好友关系
    await this.friendshipRepository.remove(friendship);

    // 更新双方的好友计数
    await this.userRepository.decrement({ id: userId }, 'followingCount', 1);
    await this.userRepository.decrement({ id: friendId }, 'followingCount', 1);
    await this.userRepository.decrement({ id: userId }, 'followersCount', 1);
    await this.userRepository.decrement({ id: friendId }, 'followersCount', 1);
  }

  /**
   * 拉黑用户
   */
  async blockUser(targetUserId: number, userId: number): Promise<void> {
    if (targetUserId === userId) {
      throw new BadRequestException('不能拉黑自己');
    }

    // 查找现有关系
    const existingRelation = await this.friendshipRepository.findOne({
      where: [
        { userId, friendId: targetUserId },
        { userId: targetUserId, friendId: userId },
      ],
    });

    if (existingRelation) {
      // 如果已是好友，先更新计数
      if (existingRelation.status === FriendshipStatus.ACCEPTED) {
        await this.userRepository.decrement(
          { id: userId },
          'followingCount',
          1,
        );
        await this.userRepository.decrement(
          { id: targetUserId },
          'followingCount',
          1,
        );
        await this.userRepository.decrement(
          { id: userId },
          'followersCount',
          1,
        );
        await this.userRepository.decrement(
          { id: targetUserId },
          'followersCount',
          1,
        );
      }
      // 删除现有关系
      await this.friendshipRepository.remove(existingRelation);
    }

    // 创建拉黑记录
    const blockRecord = this.friendshipRepository.create({
      userId,
      friendId: targetUserId,
      status: FriendshipStatus.BLOCKED,
    });

    await this.friendshipRepository.save(blockRecord);
  }

  /**
   * 取消拉黑
   */
  async unblockUser(targetUserId: number, userId: number): Promise<void> {
    const blockRecord = await this.friendshipRepository.findOne({
      where: {
        userId,
        friendId: targetUserId,
        status: FriendshipStatus.BLOCKED,
      },
    });

    if (!blockRecord) {
      throw new NotFoundException('未找到拉黑记录');
    }

    await this.friendshipRepository.remove(blockRecord);
  }

  /**
   * 获取好友列表
   */
  async getFriendsList(
    userId: number,
    page: number = 1,
    limit: number = 50,
  ): Promise<{
    data: User[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    // 查找所有已接受的好友关系
    const [friendships, total] = await this.friendshipRepository.findAndCount({
      where: [
        { userId, status: FriendshipStatus.ACCEPTED },
        { friendId: userId, status: FriendshipStatus.ACCEPTED },
      ],
      skip: (page - 1) * limit,
      take: limit,
      order: { updatedAt: 'DESC' },
    });

    // 提取好友ID
    const friendIds = friendships.map((f) =>
      f.userId === userId ? f.friendId : f.userId,
    );

    // 获取好友信息
    const friends = await this.userRepository.find({
      where: { id: In(friendIds) },
      select: ['id', 'username', 'email', 'avatar', 'bio'],
    });

    return {
      data: friends,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 获取待处理的好友请求列表
   */
  async getPendingRequests(
    userId: number,
    page: number = 1,
    limit: number = 20,
  ): Promise<{
    data: Friendship[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    const [requests, total] = await this.friendshipRepository.findAndCount({
      where: {
        friendId: userId,
        status: FriendshipStatus.PENDING,
      },
      order: { createdAt: 'DESC' },
      skip: (page - 1) * limit,
      take: limit,
    });

    return {
      data: requests,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 获取我发送的好友请求列表
   */
  async getSentRequests(
    userId: number,
    page: number = 1,
    limit: number = 20,
  ): Promise<{
    data: Friendship[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    const [requests, total] = await this.friendshipRepository.findAndCount({
      where: {
        userId,
        status: FriendshipStatus.PENDING,
      },
      order: { createdAt: 'DESC' },
      skip: (page - 1) * limit,
      take: limit,
    });

    return {
      data: requests,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 检查是否是好友
   */
  async isFriend(userId: number, targetUserId: number): Promise<boolean> {
    const friendship = await this.friendshipRepository.findOne({
      where: [
        { userId, friendId: targetUserId, status: FriendshipStatus.ACCEPTED },
        {
          userId: targetUserId,
          friendId: userId,
          status: FriendshipStatus.ACCEPTED,
        },
      ],
    });

    return !!friendship;
  }

  /**
   * 搜索用户（用于添加好友）
   */
  async searchUsers(
    keyword: string,
    currentUserId: number,
    page: number = 1,
    limit: number = 20,
  ): Promise<{
    data: Array<User & { friendshipStatus: string | null }>;
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    // 搜索用户（按用户名或邮箱）
    const queryBuilder = this.userRepository
      .createQueryBuilder('user')
      .where('user.id != :currentUserId', { currentUserId })
      .andWhere('(user.username LIKE :keyword OR user.email LIKE :keyword)', {
        keyword: `%${keyword}%`,
      })
      .select([
        'user.id',
        'user.username',
        'user.email',
        'user.avatar',
        'user.bio',
      ])
      .skip((page - 1) * limit)
      .take(limit);

    const [users, total] = await queryBuilder.getManyAndCount();

    // 查询当前用户与搜索结果的好友关系
    const userIds = users.map((u) => u.id);
    const friendships = await this.friendshipRepository.find({
      where: [
        { userId: currentUserId, friendId: In(userIds) },
        { userId: In(userIds), friendId: currentUserId },
      ],
    });

    // 合并好友状态
    const usersWithStatus = users.map((user) => {
      const friendship = friendships.find(
        (f) =>
          (f.userId === currentUserId && f.friendId === user.id) ||
          (f.friendId === currentUserId && f.userId === user.id),
      );

      return {
        ...user,
        friendshipStatus: friendship ? friendship.status : null,
      };
    });

    return {
      data: usersWithStatus as any,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }
}
